#ifndef PTRLIST_H
#define PTRLIST_H
#include "type.h"
#include "ptrarray.h"
template <typename T>
class PtrList 
{
public:
	PtrList(bool is_destroy=true):is_destroy(is_destroy)
	{
		firstBlock(4);
	}
	PtrList(uint32 capacity,bool is_destroy):is_destroy(is_destroy)
	{
		firstBlock(capacity+2); 
	}
	~PtrList(){destroy();}
	void push(T* x)
	{
		if(walker==curr_tail)
			expand();
		*(walker)=x;
		size++;
		tail=walker; 
		walker++;
	}
	void copyTo(PtrArray<T>& des)
	{
		uint32 length=init_length;
		T** read=head;
		uint32 k=0;
		for(uint32 i=0;i<block_count;i++)
		{
			uint32 j=1;
			while(j<length-1&&k<size)
			{
				*(des.sptr->space+k)=*(read+j);
				j++;
				k++;
			}
			read=reinterpret_cast<T**>(*(read+length-1));
			length<<=1;
		}
	}
	uint32 size; 
private:
	void expand()
	{
		curr_length<<=1;
		T** next=new T*[curr_length];
		block_count++;
		*(walker)=reinterpret_cast<T*>(next);
		walker=next;
		*(walker)=reinterpret_cast<T*>(curr_head);
		curr_tail=walker+curr_length-1;
		walker++;
		curr_head=next;
	}
	void firstBlock(uint32 capacity)
	{
		size=0;
		init_length=capacity;
		curr_length=init_length;
		T** next=new T*[curr_length];
		next[0]=0;
		block_count=1;
		head=next;
		walker=head+1;
		curr_head=head;
		curr_tail=head+curr_length-1;
	}
	void destroy()
	{
		T** tmp=NULL;
		if(!is_destroy)
		{
			for(uint32 i=0;i<block_count;i++)
			{
				tmp=reinterpret_cast<T**>(*(curr_head));
				delete[] curr_head;
				curr_head=tmp;
			}
		}
		else
		{
			uint32 length=init_length<<(block_count-1);
			for(uint32 i=block_count;i>0;i--)
			{
				uint32 j=1;
				tmp=reinterpret_cast<T**>(*(curr_head));
				while((i!=block_count&&j<length-1)||
					(j<length-1&&curr_head+j<=tail&&i==block_count))
				{
					delete *(curr_head+j);
					j++;
				}
				delete[] curr_head;
				curr_head=tmp;
				length>>=1;
			}
		}
	}
	T** head;
	T** curr_tail;
	T** tail;
	T** walker;
	T** curr_head;
	uint32 curr_length;
	uint32 init_length;
	bool is_destroy;
	uint32 block_count;
};
#endif //PTRLIST_H